package com.leadingsoft.pwxk.service.impl;

import java.text.DecimalFormat;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import javax.persistence.EntityManager;

import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.leadingsoft.common.exception.DataValidateException;
import com.leadingsoft.pwxk.dto.CategoryDto;
import com.leadingsoft.pwxk.dto.SearchDto;
import com.leadingsoft.pwxk.model.QAirQcPollution;
import com.leadingsoft.pwxk.model.QBaseInfo;
import com.leadingsoft.pwxk.model.QDrainInfoWaterApplyCountTwo;
import com.leadingsoft.pwxk.model.QLatestData;
import com.leadingsoft.pwxk.model.QLicenseInfo;
import com.leadingsoft.pwxk.model.QPwBaseInfo;
import com.leadingsoft.pwxk.service.CategoryService;
import com.leadingsoft.pwxk.service.PwxkGisService;
import com.querydsl.core.Tuple;
import com.querydsl.jpa.impl.JPAQuery;

@Service
public class PwxkGisServiceImpl implements PwxkGisService {

	QLicenseInfo qLicenseInfo = QLicenseInfo.licenseInfo;
	QPwBaseInfo qPwBaseInfo = QPwBaseInfo.pwBaseInfo;
	QBaseInfo qBaseInfo = QBaseInfo.baseInfo;
	QDrainInfoWaterApplyCountTwo qDrainInfoWaterApplyCountTwo = QDrainInfoWaterApplyCountTwo.drainInfoWaterApplyCountTwo;

	QAirQcPollution qAirQcPollution = QAirQcPollution.airQcPollution;

	QLatestData qLatestData = QLatestData.latestData;

	@Autowired
	private EntityManager em;

	@Autowired
	CategoryService categoryService;

	@Override
	public List<Map<String, Object>> getPwxkList(SearchDto search) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		JPAQuery<Tuple> query = new JPAQuery<Tuple>(em);
		getFilterBox(query, search);
		query.select(qLicenseInfo.xkzNum, qLicenseInfo.fztime, qPwBaseInfo.longitude, qPwBaseInfo.latitude,
				qPwBaseInfo.devcompany, qPwBaseInfo.hyname, qPwBaseInfo.dataid);
		query.from(qLatestData).leftJoin(qLicenseInfo).on(qLatestData.dataid.eq(qLicenseInfo.dataid));
		query.leftJoin(qPwBaseInfo).on(qLicenseInfo.dataid.eq(qPwBaseInfo.dataid)).leftJoin(qBaseInfo)
				.on(qBaseInfo.enterid.eq(qPwBaseInfo.enterid));
		List<Tuple> fetch = query.fetch();
		fetch.forEach(t -> {
			Map<String, Object> map = new HashMap<String, Object>();
			map.put("xkzMun", t.get(0, String.class));
			map.put("fztime", t.get(1, String.class));
			map.put("long", t.get(2, String.class));
			map.put("lat", t.get(3, String.class));
			map.put("devcompany", t.get(4, String.class));
			map.put("hyname", t.get(5, String.class));
			map.put("dataid", t.get(6, String.class));
			list.add(map);
		});
		return list;
	}

	@Override
	public List<Map<String, Object>> getLicenseStatiscal(SearchDto search) {
		List<Map<String, Object>> list = new ArrayList<Map<String, Object>>();
		JPAQuery<Tuple> query = new JPAQuery<Tuple>(em);
		getFilterBox(query, search);
		query.select(qLicenseInfo.dataid.countDistinct(), qBaseInfo.code_region, qBaseInfo.name_region);
		query.from(qLatestData).leftJoin(qLicenseInfo).on(qLatestData.dataid.eq(qLicenseInfo.dataid));
		query.leftJoin(qPwBaseInfo).on(qLicenseInfo.dataid.eq(qPwBaseInfo.dataid)).leftJoin(qBaseInfo)
				.on(qBaseInfo.enterid.eq(qPwBaseInfo.enterid));
		query.groupBy(qBaseInfo.code_region, qBaseInfo.name_region);
		query.orderBy(qBaseInfo.code_region.asc());
		List<Tuple> fetch = query.fetch();
		fetch.forEach(t -> {
			Map<String, Object> temp = new HashMap<String, Object>();
			temp.put("code", t.get(1, String.class));
			temp.put("num", t.get(0, Integer.class));
			temp.put("name", t.get(2, String.class));
			list.add(temp);
		});
		return list;
	}

	private void getFilterBox(JPAQuery<Tuple> query, SearchDto search) {
		if (StringUtils.isNotBlank(search.getHyid())) {
			List<CategoryDto> childs = categoryService.findByCodeChilds(search.getHyid());
			List<String> hyids = new ArrayList<String>(128);
			if (childs != null && !childs.isEmpty()) {
				childs.forEach(t -> {
					getAllHyid(t.getChilds(), t, hyids);
				});
				query.where(qPwBaseInfo.hyid.in(hyids));
			}
		}
		if (StringUtils.isNotBlank(search.getCodeRegion())) {
			query.where(qBaseInfo.code_region.eq(search.getCodeRegion()));
		}
		if (StringUtils.isNotBlank(search.getCodeWsystem())) {
			query.where(qBaseInfo.cod_wsystem.eq(search.getCodeWsystem()));
		}
	}

	@Override
	public List<Map<String, Object>> getGisStatiscal(SearchDto search) {
		if (null == search.getPollutantEnum() || StringUtils.isBlank(search.getYear())) {
			throw new DataValidateException("统计污染物类型或者年份不能为空");
		}
		JPAQuery<Tuple> query = new JPAQuery<Tuple>(em);
		gsCommonBuild(query, search);
		return buildFilterBox(search, query, "gas");
	}

	private void gsCommonBuild(JPAQuery<Tuple> query, SearchDto search) {
		query.select(qAirQcPollution.qconeyear, qAirQcPollution.qctwoyear, qAirQcPollution.qcthreeyear,
				qAirQcPollution.qcfouryear, qAirQcPollution.qcfiveyear, qBaseInfo.name_region, qBaseInfo.wsystemname,
				qLicenseInfo.fztime, qAirQcPollution.wrwid, qBaseInfo.code_region);
		query.from(qLatestData).leftJoin(qLicenseInfo).on(qLatestData.dataid.eq(qLicenseInfo.dataid));
		query.leftJoin(qAirQcPollution).on(qLicenseInfo.dataid.eq(qAirQcPollution.dataid)).leftJoin(qPwBaseInfo)
				.on(qLicenseInfo.dataid.eq(qPwBaseInfo.dataid)).leftJoin(qBaseInfo)
				.on(qPwBaseInfo.enterid.eq(qBaseInfo.enterid));
		query.where(qAirQcPollution.wrwid.in(search.getPollutantEnum().getCode()));
	}

	private List<Map<String, Object>> buildFilterBox(SearchDto s, JPAQuery<Tuple> query, String type) {
		if (StringUtils.isNotBlank(s.getCodeRegion())) {
			query.where(qBaseInfo.code_region.eq(s.getCodeRegion()));
		}
		if (StringUtils.isNotBlank(s.getHyid())) {
			List<CategoryDto> childs = categoryService.findByCodeChilds(s.getHyid());
			List<String> hyids = new ArrayList<String>(128);
			if (childs != null && !childs.isEmpty()) {
				childs.forEach(t -> {
					getAllHyid(t.getChilds(), t, hyids);
				});
				query.where(qPwBaseInfo.hyid.in(hyids));
			}
		}
		if (StringUtils.isNotBlank(s.getCodeWsystem())) {
			query.where(qBaseInfo.cod_wsystem.eq(s.getCodeWsystem()));
		}
		query.orderBy(qBaseInfo.code_region.asc());
		if (type.equals("gas")) {
			return getGasResult(query, Integer.parseInt(s.getYear()));
		}
		if (type.equals("water")) {
			return getWaterResult(query, Integer.parseInt(s.getYear()));
		}
		return null;
	}

	private List<Map<String, Object>> getGasResult(JPAQuery<Tuple> query, Integer year) {
		// 数据 集合
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		List<Map<String, String>> data = new ArrayList<Map<String, String>>();
		List<Tuple> fetch = query.fetch();
		fetch.forEach(t -> {
			Map<String, String> tempMap = new HashMap<String, String>();
			tempMap.put("qconeyear", t.get(qAirQcPollution.qconeyear));
			tempMap.put("qctwoyear", t.get(qAirQcPollution.qctwoyear));
			tempMap.put("qcthreeyear", t.get(qAirQcPollution.qcthreeyear));
			tempMap.put("qcfouryear", t.get(qAirQcPollution.qcfouryear));
			tempMap.put("qcfiveyear", t.get(qAirQcPollution.qcfiveyear));
			tempMap.put("code", t.get(qBaseInfo.code_region));
			tempMap.put("name", t.get(qBaseInfo.name_region));
			tempMap.put("fztime", t.get(qLicenseInfo.fztime));
			data.add(tempMap);
		});
		// 名称集合
		Map<String, String> map = new LinkedHashMap<String, String>();
		data.forEach((val) -> {
			map.put(val.get("code"), val.get("name"));
		});
		DecimalFormat decimalFormat = new DecimalFormat();
		decimalFormat.applyPattern("0.000000");
		for (String t : map.keySet()) {
			double total = 0.0;
			for (Map<String, String> val : data) {
				if (t.equals(val.get("code"))) {
					total = dealGasSum(val, year, total);
				}
			}
			Map<String, Object> temp = new HashMap<String, Object>();
			temp.put("code", t);
			temp.put("num", decimalFormat.format(total));
			temp.put("name", map.get(t));
			result.add(temp);
		}
		return result;
	}

	private double dealGasSum(Map<String, String> val, Integer year, double total) {
		Integer fzYear = Integer.parseInt(val.get("fztime").substring(0, 4));
		Integer fzMonth = Integer.parseInt(val.get("fztime").substring(5, 7));
		Integer fzDay = Integer.parseInt(val.get("fztime").substring(8, 10));
		if (fzDay > 15) {
			if (fzMonth < 12) {
				fzMonth++;
			}
		}
		double qconeyear = 0.0;
		double qctwoyear = 0.0;
		double qcthreeyear = 0.0;
		double qcfouryear = 0.0;
		double qcfiveyear = 0.0;
		double temp = 0.0;
		DecimalFormat decimalFormat = new DecimalFormat();
		decimalFormat.applyPattern("0.000000");
		if (null != val.get("qconeyear") && !val.get("qconeyear").equals("/") && !val.get("qconeyear").equals("")) {
			qconeyear = Double.valueOf(val.get("qconeyear"));
		}
		if (null != val.get("qctwoyear") && !val.get("qctwoyear").equals("/") && !val.get("qctwoyear").equals("")) {
			qctwoyear = Double.valueOf(val.get("qctwoyear"));
		}
		if (null != val.get("qcthreeyear") && !val.get("qcthreeyear").equals("/")
				&& !val.get("qcthreeyear").equals("")) {
			qcthreeyear = Double.valueOf(val.get("qcthreeyear"));
		}
		if (null != val.get("qcfouryear") && !val.get("qcfouryear").equals("/") && !val.get("qcfouryear").equals("")) {
			qcfouryear = Double.valueOf(val.get("qcfouryear"));
		}
		if (null != val.get("qcfiveyear") && !val.get("qcfiveyear").equals("/") && !val.get("qcfiveyear").equals("")) {
			qcfiveyear = Double.valueOf(val.get("qcfiveyear"));
		}
		switch (year - fzYear) {
		case 0:
			temp = qconeyear * (12 - fzMonth) / 12;
			break;
		case 1:
			temp = qctwoyear * (12 - fzMonth) / 12 + qconeyear * fzMonth / 12;
			break;
		case 2:
			temp = qcthreeyear * (12 - fzMonth) / 12 + qctwoyear * fzMonth / 12;
			break;
		case 3:
			temp = qcfouryear * (12 - fzMonth) / 12 + qcthreeyear * fzMonth / 12;
			break;
		case 4:
			temp = qcfiveyear * (12 - fzMonth) / 12 + qcfouryear * fzMonth / 12;
			break;
		default:
			break;
		}
		total += Double.valueOf(decimalFormat.format(temp));
		return total;
	}

	@Override
	public List<Map<String, Object>> getWaterStatiscal(SearchDto search) {
		if (null == search.getPollutantEnum() || StringUtils.isBlank(search.getYear())) {
			throw new DataValidateException("统计污染物类型或者年份不能为空");
		}
		JPAQuery<Tuple> query = new JPAQuery<Tuple>(em);
		waterCommonBuild(query, search);
		return buildFilterBox(search, query, "water");
	}

	private void waterCommonBuild(JPAQuery<Tuple> query, SearchDto search) {
		query.select(qDrainInfoWaterApplyCountTwo.sqoneyear, qDrainInfoWaterApplyCountTwo.sqtwoyear,
				qDrainInfoWaterApplyCountTwo.sqthreeyear, qDrainInfoWaterApplyCountTwo.sqfouryear,
				qDrainInfoWaterApplyCountTwo.sqfiveyear, qLicenseInfo.fztime, qBaseInfo.name_region,
				qDrainInfoWaterApplyCountTwo.waterwrwname, qDrainInfoWaterApplyCountTwo.waterwrwcode,
				qBaseInfo.code_region);
		query.from(qLatestData).leftJoin(qLicenseInfo).on(qLatestData.dataid.eq(qLicenseInfo.dataid));
		query.leftJoin(qDrainInfoWaterApplyCountTwo).on(qLicenseInfo.dataid.eq(qDrainInfoWaterApplyCountTwo.dataid))
				.leftJoin(qPwBaseInfo).on(qLicenseInfo.dataid.eq(qPwBaseInfo.dataid)).leftJoin(qBaseInfo)
				.on(qPwBaseInfo.enterid.eq(qBaseInfo.enterid));
		query.where(qDrainInfoWaterApplyCountTwo.waterwrwcode.in(search.getPollutantEnum().getCode()));
	}

	private List<Map<String, Object>> getWaterResult(JPAQuery<Tuple> query, Integer year) {
		// 数据 集合
		List<Map<String, Object>> result = new ArrayList<Map<String, Object>>();
		List<Map<String, String>> data = new ArrayList<Map<String, String>>();
		List<Tuple> fetch = query.fetch();
		fetch.forEach(t -> {
			Map<String, String> tempMap = new HashMap<String, String>();
			tempMap.put("sqoneyear", t.get(qDrainInfoWaterApplyCountTwo.sqoneyear));
			tempMap.put("sqtwoyear", t.get(qDrainInfoWaterApplyCountTwo.sqtwoyear));
			tempMap.put("sqthreeyear", t.get(qDrainInfoWaterApplyCountTwo.sqthreeyear));
			tempMap.put("sqfouryear", t.get(qDrainInfoWaterApplyCountTwo.sqfouryear));
			tempMap.put("sqfiveyear", t.get(qDrainInfoWaterApplyCountTwo.sqfiveyear));
			tempMap.put("fztime", t.get(qLicenseInfo.fztime));
			tempMap.put("code", t.get(qBaseInfo.code_region));
			tempMap.put("name", t.get(qBaseInfo.name_region));
			tempMap.put("waterwrwcode", t.get(qDrainInfoWaterApplyCountTwo.waterwrwcode));
			data.add(tempMap);
		});
		// 名称集合
		Map<String, String> map = new LinkedHashMap<String, String>();
		data.forEach((val) -> {
			map.put(val.get("code"), val.get("name"));
		});
		DecimalFormat decimalFormat = new DecimalFormat();
		decimalFormat.applyPattern("0.000000");
		for (String t : map.keySet()) {
			double total = 0.0;
			for (Map<String, String> val : data) {
				if (t.equals(val.get("code"))) {
					total = dealWaterSum(val, year, total);
				}
			}
			Map<String, Object> temp = new HashMap<String, Object>();
			temp.put("code", t);
			temp.put("num", decimalFormat.format(total));
			temp.put("name", map.get(t));
			result.add(temp);
		}
		return result;
	}

	private double dealWaterSum(Map<String, String> val, Integer year, double total) {
		Integer fzYear = Integer.parseInt(val.get("fztime").substring(0, 4));
		Integer fzMonth = Integer.parseInt(val.get("fztime").substring(5, 7));
		Integer fzDay = Integer.parseInt(val.get("fztime").substring(8, 10));
		if (fzDay > 15) {
			if (fzMonth < 12) {
				fzMonth++;
			}
		}
		DecimalFormat decimalFormat = new DecimalFormat();
		decimalFormat.applyPattern("0.000000");
		double sqoneyear = 0.0;
		double sqtwoyear = 0.0;
		double sqthreeyear = 0.0;
		double sqfouryear = 0.0;
		double sqfiveyear = 0.0;
		Double temp = 0.0;
		if (null != val.get("sqoneyear") && !val.get("sqoneyear").equals("/") && !val.get("sqoneyear").equals("")) {
			sqoneyear = Double.valueOf(val.get("sqoneyear"));
		}
		if (null != val.get("sqtwoyear") && !val.get("sqtwoyear").equals("/") && !val.get("sqtwoyear").equals("")) {
			sqtwoyear = Double.valueOf(val.get("sqtwoyear"));
		}
		if (null != val.get("sqthreeyear") && !val.get("sqthreeyear").equals("/")
				&& !val.get("sqthreeyear").equals("")) {
			sqthreeyear = Double.valueOf(val.get("sqthreeyear"));
		}
		if (null != val.get("sqfouryear") && !val.get("sqfouryear").equals("/") && !val.get("sqfouryear").equals("")) {
			sqfouryear = Double.valueOf(val.get("sqfouryear"));
		}
		if (null != val.get("sqfiveyear") && !val.get("sqfiveyear").equals("/") && !val.get("sqfiveyear").equals("")) {
			sqfiveyear = Double.valueOf(val.get("sqfiveyear"));
		}
		switch (year - fzYear) {
		case 0:
			temp = sqoneyear * (12 - fzMonth) / 12;
			break;
		case 1:
			temp = sqtwoyear * (12 - fzMonth) / 12 + sqoneyear * fzMonth / 12;
			break;
		case 2:
			temp = sqthreeyear * (12 - fzMonth) / 12 + sqtwoyear * fzMonth / 12;
			break;
		case 3:
			temp = sqfouryear * (12 - fzMonth) / 12 + sqthreeyear * fzMonth / 12;
			break;
		case 4:
			temp = sqfiveyear * (12 - fzMonth) / 12 + sqfouryear * fzMonth / 12;
			break;
		default:
			break;
		}
		total += Double.valueOf(decimalFormat.format(temp));
		return total;
	}

	private List<String> getAllHyid(List<CategoryDto> childs, CategoryDto parent, List<String> result) {
		if (null != childs && !childs.isEmpty()) {
			childs.forEach(t -> {
				getAllHyid(t.getChilds(), t, result);
			});
		}
		if (null != parent) {
			result.add(parent.getCode());
		}
		return result;
	}
}
